package com.ai.bitcoin.service.impl;

import com.ai.bitcoin.bo.MemberCenterBitcoinsBO;
import com.ai.bitcoin.bo.MemberCenterIndexBO;
import com.ai.bitcoin.bo.MemberCenterUpateStatusBO;
import com.ai.bitcoin.constant.CommonConstant;
import com.ai.bitcoin.constant.QrCodeConstant;
import com.ai.bitcoin.exception.BussinessRuntimeException;
import com.ai.bitcoin.jpa.dao.*;
import com.ai.bitcoin.jpa.entity.*;
import com.ai.bitcoin.service.MemberCenterService;
import com.ai.bitcoin.service.helper.WeiXinServiceHelper;
import com.ai.bitcoin.vo.MemberCenterIndexAccounVO;
import com.ai.bitcoin.vo.MemberCenterIndexBaseInfoVO;
import com.ai.bitcoin.vo.MemberCenterIndexRankVO;
import com.ai.bitcoin.vo.MemberCenterIndexVO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import javax.persistence.criteria.Predicate;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * @description: ${description}
 * @author: gulj
 * @create: 2018-07-07 17:02
 **/
@Service
@Slf4j
public class MemberCenterServiceImpl implements MemberCenterService {

    @Autowired
    private WeiXinServiceHelper weiXinServiceHelper;

    @Autowired
    private BccUserDao bccUserDao;

    @Autowired
    private BccUserBonusConfigDao userBonusConfigDao;

    @Autowired
    private BccBasicInfoDao bccBasicInfoDao;

    @Autowired
    private BccSubCoinDao bccSubCoinDao;

    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private BccUserPlcRecordDao bccUserPlcRecordDao;

    @Autowired
    private BccUserBonusLogDao userBonusLogDao;

    public BccUser queryBccUser(String openId) {
        return bccUserDao.findByOpenId(openId);
    }

    public int computeMyRank(String openId) {
        if (StringUtils.isEmpty(openId)) {
            throw new BussinessRuntimeException(1001, "openId 为空。非法访问。");
        }
        return bccUserDao.computeMyRank(openId);
    }

    @Override
    public MemberCenterIndexVO index(MemberCenterIndexBO memberCenterIndexBO) {
        String openId = memberCenterIndexBO.getOpenId();
        BccUser bccUser = queryBccUser(openId);
        if (bccUser == null) {
            throw new BussinessRuntimeException(1001, "openId 不合法");
        }

        MemberCenterIndexVO memberCenterIndexVO = new MemberCenterIndexVO();

        // 基础信息
        MemberCenterIndexBaseInfoVO baseInfoVO = new MemberCenterIndexBaseInfoVO();
        baseInfoVO.setImageUrl(bccUser.getImage());
        baseInfoVO.setPlcAmount(bccUser.getBonus());
        baseInfoVO.setPlcDetailLink(CommonConstant.BITCOIN_PLC_PREFIX + openId + CommonConstant.PNG_POSTFIX);
        baseInfoVO.setInviteNum(bccUserDao.queryByParentOpenId(openId));
        baseInfoVO.setRankRate(computeMyRank(openId));
        memberCenterIndexVO.setBaseInfoVO(baseInfoVO);
        return memberCenterIndexVO;
    }


    /**
     * 订阅列表
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<BccBasicInfo> bitcoins(MemberCenterBitcoinsBO bitcoinsBO) {

        List<BccBasicInfo> bccList;
        // 新增币的列表
        if (bitcoinsBO.getStatus().equals("-1")) {
            bccList = bccBasicInfoDao.findUserUnsubscribedList(bitcoinsBO.getOpenId());
        }
        else {
            bccList = bccBasicInfoDao.findUserSubscribedList(bitcoinsBO.getOpenId());
        }
        return bccList;
    }

    @Override
    @SuppressWarnings("unchecked")
    //删除userBitCoins缓存
    public void updateStatus(MemberCenterUpateStatusBO updateStatusBO) {
        // 取消关注,或者订阅
        String status = updateStatusBO.getStatus();

        // 关注或者订阅
        BccSubCoin bccSubCoin = bccSubCoinDao.findByUserOpenIdAndBccId(updateStatusBO.getOpenId(), updateStatusBO.getBccId());
        if (bccSubCoin == null) {
            bccSubCoin = new BccSubCoin();
            bccSubCoin.setBccId(updateStatusBO.getBccId());
            bccSubCoin.setBccName(updateStatusBO.getBccName());
            bccSubCoin.setCreateTime(new Date());
            bccSubCoin.setUserOpenId(updateStatusBO.getOpenId());
            bccSubCoin.setEndTime(0L);
            bccSubCoin.setSource("simply");
            bccSubCoin.setStatus(0);
        }
        switch (status) {
            //订阅
            case "1":
                bccSubCoin.setStatus(1);
                bccSubCoin.setEndTime(DateUtils.addMonths(new Date(), 1).getTime());
                break;
            case "2":
                bccSubCoin.setEndTime(0L);
                bccSubCoin.setStatus(0);
                break;
            default:
                return;
        }
        bccSubCoin.setUpdateTime(new Date());
        bccSubCoinDao.save(bccSubCoin);
    }


    @Override
    public MemberCenterIndexAccounVO queryBccUserPLcRecord(String openId) {
        MemberCenterIndexAccounVO indexAccounVO = new MemberCenterIndexAccounVO();

        //一个月内的消费记录
        List<BccUserBonusLog> bonusLogList = userBonusLogDao.findAll((Specification<BccUserBonusLog>) (root, query, cb) -> {
            List<Predicate> predicateList = Lists.newArrayList();
            predicateList.add(cb.equal(root.get("openId").as(String.class), openId));
            predicateList.add(cb.greaterThanOrEqualTo(root.get("eventDate").as(Date.class), DateUtils.addMonths(new Date(), -1)));
            return cb.and(predicateList.toArray(new Predicate[0]));
        });
        List<BccUserPlcRecord> userPlcRecords = bccUserPlcRecordDao.findAll((Specification<BccUserPlcRecord>) (root, query, cb) -> {
            List<Predicate> predicateList = Lists.newArrayList();
            predicateList.add(cb.equal(root.get("openId").as(String.class), openId));
            predicateList.add(cb.greaterThanOrEqualTo(root.get("ceateTime").as(Date.class), DateUtils.addMonths(new Date(), -1)));
            return cb.and(predicateList.toArray(new Predicate[0]));
        });
        //合并记录
        for (BccUserBonusLog log : bonusLogList) {
            BccUserPlcRecord record = new BccUserPlcRecord();
            record.setCeateTime(log.getEventDate());
            record.setOpenId(openId);
            record.setPlc(log.getBonusNumber().doubleValue());
            record.setReason(log.getConfig().getEventTypeName());
            record.setType(Integer.valueOf(log.getEventTypeCd()));
            userPlcRecords.add(record);
        }
        //降序
        userPlcRecords.sort((t0, t1) -> t1.getCeateTime().compareTo(t0.getCeateTime()));
        indexAccounVO.setPlcRecordList(userPlcRecords);
        //  邀请的人数
        int invitedNum = bccUserDao.queryByParentOpenId(openId);

        // 排名
        List<Object[]> objects = bccUserPlcRecordDao.queryRankAndInvitedNum(openId);
        if (objects == null || objects.isEmpty()) {
            int invitedTotal = bccUserPlcRecordDao.countInvitedTotal();
            Random random = new Random();
            int randomNum = random.nextInt(30);
            indexAccounVO.setRankNum(randomNum + invitedTotal);
            indexAccounVO.setInvitedNum(invitedNum);
        }
        else {
            MemberCenterIndexRankVO indexRankVO = null;
            if (objects.get(0) != null) {
                indexRankVO = new MemberCenterIndexRankVO();
                String[] split = objects.get(0)[0].toString().split("\\.");
                indexRankVO.setRank(Integer.valueOf(split[0]));
                indexRankVO.setOpenId(objects.get(0)[1].toString());
                indexRankVO.setInvitedNum(invitedNum);
            }

            if (indexRankVO != null) {
                indexAccounVO.setRankNum(indexRankVO.getRank());
                indexAccounVO.setInvitedNum(invitedNum);
            }
        }

        // plc余额
        BccUser bccUser = bccUserDao.findByOpenId(openId);
        if (bccUser != null) {
            indexAccounVO.setPlcLeftAmount(bccUser.getBonus());
        }

        return indexAccounVO;
    }

    /**
     * 取得用户海报地址
     *
     * @param openId
     */
    @Override
    public String getPosterUrl(String openId) {
        try {
            File file = getPoster(openId);
            WxMediaImgUploadResult result = wxMpService.getMaterialService().mediaImgUpload(file);
            return result.getUrl();
        } catch (Exception e) {
            log.warn("取得海报地址失败", e);
            return null;
        }
    }

    /**
     * 取得用户海报
     *
     * @param openId
     * @throws IOException
     */
    @Override
    public File getPoster(String openId) throws IOException {
        BccUser user = bccUserDao.findByOpenId(openId);
        //参与人总量
        long participantCount = bccUserDao.count();
        //已经发放PLC总量
        long bonusTotal = bccUserDao.getBonusTotal();
        //关注奖励
        BigDecimal maxSubBonus = userBonusConfigDao.findByEventTypeCd("0101").getMaxNumber();
        //邀请关注奖励
        BigDecimal maxInviteBonus = userBonusConfigDao.findByEventTypeCd("0103").getMaxNumber();
        //模板图片
        BufferedImage srcImage = ImageIO.read(new URL("http://tianru-cdn.valuechain.group/poster.jpg"));

        String nickNameLine = StringUtils.defaultString(user.getNickname());
        String shareContentLine = "邀请您一起分享1000万PLC";
        String visitContentLine = "现" + participantCount + "位参与者已瓜分" + bonusTotal + "个PLC";
        String subContentLine = "关注即免费获取最高" + maxSubBonus + "PLC";
        String inviteContentLine = "每成功邀请一人即送最高" + maxInviteBonus + "PLC";
        int averageWidth = srcImage.getWidth() / 2;
        //全局字体大小
        int fontSize = 22;
        //全局字体
        Font defaultFont = new Font("微软雅黑", Font.PLAIN, fontSize);
        FontMetrics fm = sun.font.FontDesignMetrics.getMetrics(defaultFont);


        Color defaultColor = new Color(0x00A8A3);
        //图片宽度
        int imageSize = 140;
        //坐标
        Map<String, List<Integer>> xyMap = Maps.newLinkedHashMap();
        //坐标配置
        xyMap.put("qrCodeImage", Lists.newArrayList(averageWidth - imageSize - 10, 1032));
        xyMap.put("headImage", Lists.newArrayList(299, 115));
        xyMap.put("nickName", Lists.newArrayList(averageWidth - (fm.stringWidth(nickNameLine) / 2), 287 + 22));
        xyMap.put("shareContent", Lists.newArrayList(averageWidth - (fm.stringWidth(shareContentLine) / 2), 323 + 22));
        xyMap.put("visitLine", Lists.newArrayList(averageWidth - (fm.stringWidth(visitContentLine) / 2), 696 + 22));
        xyMap.put("sub", Lists.newArrayList(averageWidth - (fm.stringWidth(subContentLine) / 2), 831 + 22));
        xyMap.put("invite", Lists.newArrayList(averageWidth - (fm.stringWidth(inviteContentLine) / 2) - 6 * 2, 889 + 22));
        xyMap.put("add", Lists.newArrayList(431, 1213 + 22));

        if (StringUtils.isEmpty(user.getShareQrcodeUrl())) {
            String qrCodeUrl = weiXinServiceHelper.generatePermanentQrcode(QrCodeConstant.PERMANET_SHARE_QRCODE + openId);
            user.setShareQrcodeUrl(qrCodeUrl);
            user = bccUserDao.save(user);
        }
        //二维码
        BufferedImage qrCode = ImageIO.read(new URL(user.getShareQrcodeUrl()));
        Graphics2D g = srcImage.createGraphics();
        g.drawImage(qrCode, xyMap.get("qrCodeImage").get(0), xyMap.get("qrCodeImage").get(1), imageSize, imageSize, null);
        //用户头像
        if (StringUtils.isEmpty(user.getImage())) {
            try {
                WxMpUser mpUser = wxMpService.getUserService().userInfo(openId);
                user.setImage(mpUser.getHeadImgUrl());
                user.setNickname(mpUser.getNickname());
                user = bccUserDao.save(user);
            } catch (WxErrorException e) {
                log.warn("用户微信信息取得失败。{}", openId);
            }
        }


        BufferedImage headImage = ImageIO.read(new URL(StringUtils.defaultString(user.getImage(), "https://199store.oss-cn-hangzhou.aliyuncs.com/5cbf1c0a913948cfa80843324934cfc8.png")));
        srcImage.createGraphics().drawImage(headImage, xyMap.get("headImage").get(0), xyMap.get("headImage").get(1), imageSize, imageSize, null);

        Graphics2D nickName = srcImage.createGraphics();
        nickName.setFont(defaultFont);
        nickName.drawString(StringUtils.defaultString(user.getNickname(), "评链网"), xyMap.get("nickName").get(0), xyMap.get("nickName").get(1));

        Graphics2D inviteFront = srcImage.createGraphics();
        inviteFront.setFont(defaultFont);
        inviteFront.drawString("邀请您一起分享", xyMap.get("shareContent").get(0), xyMap.get("shareContent").get(1));

        //#00A8A3
        Graphics2D inviteBackend = srcImage.createGraphics();
        inviteBackend.setColor(defaultColor);
        inviteBackend.setFont(defaultFont);
        inviteBackend.drawString("1000万PLC", xyMap.get("shareContent").get(0) + fm.stringWidth("邀请您一起分享"), xyMap.get("shareContent").get(1));

        Graphics2D visit1 = srcImage.createGraphics();
        visit1.setFont(defaultFont);
        visit1.drawString("现", xyMap.get("visitLine").get(0), xyMap.get("visitLine").get(1));

        Graphics2D visit2 = srcImage.createGraphics();
        visit2.setFont(defaultFont);
        visit2.setColor(defaultColor);
        visit2.drawString(String.valueOf(participantCount), xyMap.get("visitLine").get(0) + fm.stringWidth("现"), xyMap.get("visitLine").get(1));

        Graphics2D visit3 = srcImage.createGraphics();
        visit3.setFont(defaultFont);
        visit3.drawString("位参与者已瓜分", xyMap.get("visitLine").get(0) + fm.stringWidth("现" + participantCount), xyMap.get("visitLine").get(1));


        Graphics2D visit5 = srcImage.createGraphics();
        visit5.setFont(defaultFont);
        visit5.setColor(defaultColor);
        visit5.drawString(String.valueOf(bonusTotal), xyMap.get("visitLine").get(0) + fm.stringWidth("现" + participantCount + "位参与者已瓜分"), xyMap.get("visitLine").get(1));

        Graphics2D visit6 = srcImage.createGraphics();
        visit6.setFont(defaultFont);
        visit6.drawString("个PLC", xyMap.get("visitLine").get(0) + fm.stringWidth("现" + participantCount + "位参与者已瓜分" + bonusTotal), xyMap.get("visitLine").get(1));


        Graphics2D sub1 = srcImage.createGraphics();
        sub1.setFont(defaultFont);
        sub1.drawString("关注即免费获取最高", xyMap.get("sub").get(0), xyMap.get("sub").get(1));

        Graphics2D sub2 = srcImage.createGraphics();
        sub2.setFont(defaultFont);
        sub2.setColor(defaultColor);
        sub2.drawString(maxSubBonus + "PLC", xyMap.get("sub").get(0) + fm.stringWidth("关注即免费获取最高"), xyMap.get("sub").get(1));


        Graphics2D successInvited1 = srcImage.createGraphics();
        successInvited1.setFont(defaultFont);
        successInvited1.drawString("每成功邀请一人即送最高", xyMap.get("invite").get(0), xyMap.get("invite").get(1));

        Graphics2D successInvited2 = srcImage.createGraphics();
        successInvited2.setFont(defaultFont);
        successInvited2.setColor(defaultColor);
        successInvited2.drawString(maxInviteBonus + "PLC", xyMap.get("invite").get(0) + fm.stringWidth("每成功邀请一人即送最高"), xyMap.get("invite").get(1));


        Graphics2D vvv = srcImage.createGraphics();
        vvv.setFont(new Font("Microsoft YaHei", Font.PLAIN, 25));
        vvv.drawString("获取" + maxSubBonus + "PLC", xyMap.get("add").get(0), xyMap.get("add").get(1));

        File file = new File(FileUtils.getTempDirectoryPath() + "/" + openId + ".jpg");
        ImageIO.write(srcImage, "jpg", file);
        return file;
    }
}
